#ifndef EVENT_LOOP_H
#define EVENT_LOOP_H

#include <pthread.h>
#include "channel.h"
#include "event_dispatcher.h"
#include "common.h"

extern const struct event_dispatcher poll_dispatcher;  // poll 派发器
extern const struct event_dispatcher epoll_dispatcher; // epoll 派发器

struct channel_element
{
    int type;                     //1: add  2: delete
    struct channel *channel;      // 对应的 channel
    struct channel_element *next; // 下一个 channel_element
};

// event_loop
struct event_loop
{
    int quit;                                       // 是否退出
    const struct event_dispatcher *eventDispatcher; // 事件派发器

    /** 对应的event_dispatcher的数据. */
    void *event_dispatcher_data;    // 派发数据
    struct channel_map *channelMap; // channel 哈希表

    // pending 子线程内需要处理的新事件
    int is_handle_pending;
    struct channel_element *pending_head; // 处理头
    struct channel_element *pending_tail; // 尾部

    pthread_t owner_thread_id; // 当前线程 id
    pthread_mutex_t mutex;     // 锁
    pthread_cond_t cond;       // 条件变量
    int socketPair[2];         // 用于父线程通知子线程
    char *thread_name;         // thread 名称
};

struct event_loop *event_loop_init();

struct event_loop *event_loop_init_with_name(char *thread_name);

// 运行 event_loop 实际就是一个死循环
int event_loop_run(struct event_loop *eventLoop);

// 唤醒 event_loop
void event_loop_wakeup(struct event_loop *eventLoop);

// 添加 channel
int event_loop_add_channel_event(struct event_loop *eventLoop, int fd, struct channel *channel1);

// 移除 channel
int event_loop_remove_channel_event(struct event_loop *eventLoop, int fd, struct channel *channel1);

// 更新 channel
int event_loop_update_channel_event(struct event_loop *eventLoop, int fd, struct channel *channel1);

// 添加之前的钩子
int event_loop_handle_pending_add(struct event_loop *eventLoop, int fd, struct channel *channel);

// 删除之前的钩子
int event_loop_handle_pending_remove(struct event_loop *eventLoop, int fd, struct channel *channel);

// 更新之前的钩子
int event_loop_handle_pending_update(struct event_loop *eventLoop, int fd, struct channel *channel);

// dispather派发完事件之后，调用该方法通知event_loop执行对应事件的相关callback方法
// res: EVENT_READ | EVENT_READ等
int channel_event_activate(struct event_loop *eventLoop, int fd, int res);

#endif